package com.esunny.springboot.interceptor;

import com.esunny.springboot.constant.CacheConstants;
import com.esunny.springboot.constant.Constants;
import com.esunny.springboot.pojo.dto.LoginUser;
import com.esunny.springboot.pojo.dto.Principal;
import com.esunny.springboot.utils.StringUtils;
import com.esunny.springboot.utils.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 全局拦截器，在用swagger时需要注释掉这个类,
 * 从响应结果上来看这个拦截器是在security的拦截器之前的。因为security（继承了WebSecurityConfigurerAdapter，是一些列的过滤器链路，最后有一个拦截器）。
 */
@Slf4j
// @Configuration//声明这是一个配置
public class MyInterceptor implements WebMvcConfigurer {
    @Resource(name = "stringRedisTemplate")
    private ValueOperations<String, String> sops;

    @Autowired
    private RedisService redisService;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        HandlerInterceptor inter = new HandlerInterceptor() {

            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
                System.out.println("自定义拦截器......");
                System.out.println("asdasds");
                System.out.println(redisService.getCacheObject(getTokenKey("token")).toString() + "111");
                String url = request.getServletPath();//  /user/login
                // 不需要登录的请求直接放行
                if (StringUtils.inStringIgnoreCase(url, "/doc.html", "/swagger-ui.html")) {
                    return true;
                }
                String token = getToken(request);//获取请求头中的token，这里的token是key
                LoginUser loginUser = null;
                // 没有token,又不是注册请求或登录请求，直接拒绝
                if (StringUtils.isBlank(token)) {
                    if (StringUtils.matches(url, "/user/register", "/user/login")) {
                        return true;
                    }
                    throw new Exception("未登陆");
                }
                //  有token
                if (StringUtils.isNotBlank(token)) {
                    loginUser = redisService.getCacheObject(getTokenKey(token));
                    // redis中找不到相同token，说明"登录状态已过期"
                    if (StringUtils.isNull(loginUser)) {
                        throw new Exception("登录状态已过期");
                    }
                    // // 已经登陆过了
                    if (StringUtils.matches(url, "/user/login")) {
                        throw new Exception("重复登录");//跳转到首页是最好的
                    }
                }
                if (StringUtils.isNull(loginUser.getUserId()) || StringUtils.isBlank(loginUser.getUsername())) {

                    throw new Exception("令牌验证失败");
                }
                // 刷新过期时间（720分钟）
                redisService.expire(getTokenKey(token), Constants.TOKEN_EXPIRE * 60);
                // 设置用户信息到请求中
                // Map map=request.getParameterMap();//上传的参数集合，这个只读
                request.setAttribute(CacheConstants.PRINCIPAL, generatePrincipal(loginUser));
                return true;
            }

            @Override
            public void postHandle(HttpServletRequest request, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
                    throws Exception {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterCompletion(HttpServletRequest request, HttpServletResponse arg1, Object arg2, Exception arg3)
                    throws Exception {
                // TODO Auto-generated method stub

            }
        };
        registry.addInterceptor(inter).addPathPatterns("/**");//注册上面的这个拦截器，适用于所有的请求
    }

    /**
     * 获取请求token
     */
    private String getToken(HttpServletRequest request) {

        String token = request.getHeader(CacheConstants.HEADER);
        if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX)) {
            token = token.replace(CacheConstants.TOKEN_PREFIX, "");
        }
        return token;
    }

    private String getTokenKey(String token) {
        return CacheConstants.LOGIN_TOKEN_KEY + token;
    }

    /**
     * 从redis获取的认证中提取有用的信息发给下游
     */
    private Principal generatePrincipal(LoginUser loginUser) {
        Principal principal = new Principal();
        principal.setUser(loginUser.getUser());
        principal.setRole(loginUser.getRole());
        principal.setPermissions(loginUser.getPermissions());
        return principal;
    }
}
